package com.gengzp.system.service.impl;

import com.gengzp.common.enums.PermissionEnum;
import com.gengzp.common.exception.BusinessException;
import com.gengzp.common.model.permission.dto.PermissionDto;
import com.gengzp.common.model.permission.dto.RelationRoleInfoDto;
import com.gengzp.common.model.permission.entity.UserRoleRelation;
import com.gengzp.common.model.permission.req.AssignPermissionsToRoleReq;
import com.gengzp.common.model.permission.req.AssignRoleToUserReq;
import com.gengzp.common.model.permission.resp.SearchPermissionResp;
import com.gengzp.common.model.permission.resp.SearchUserPermissionResp;
import com.gengzp.common.model.permission.resp.SearchUserRoleRelationResp;
import com.gengzp.common.model.role.entity.SysRole;
import com.gengzp.permission.utils.PermissionUtils;
import com.gengzp.system.facade.ISysRoleFacade;
import com.gengzp.system.facade.ISysUserFacade;
import com.gengzp.system.mapper.UserRoleRelationMapper;
import com.gengzp.system.service.IPermissionService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName PermissionServiceImpl
 * @Description 权限管理服务层实现
 * @Author gengzp
 * @Date 2025/5/16 21:40
 */
@Service
public class PermissionServiceImpl implements IPermissionService {

    @Autowired
    private ISysUserFacade sysUserFacade;

    @Autowired
    private ISysRoleFacade sysRoleFacade;

    @Autowired
    private UserRoleRelationMapper userRoleRelationMapper;

    @Override
    public SearchPermissionResp searchPermission() {
        // 权限编码对应名称映射
        Map<String, String> permissionCode2NameMap = Maps.newHashMap();
        // 父级权限对应子权限编码映射   key:父权限编码  value: 子权限编码集合
        Map<String, List<String>> parent2SonPermissionCodeMap = Maps.newHashMap();
        // 顶级节点编码集合
        List<String> topPermissionCodes = Lists.newArrayList();

        // 循环遍历权限枚举
        for (PermissionEnum v : PermissionEnum.values()) {
            // 拼装权限编码名称映射
            permissionCode2NameMap.put(v.getPermissionCode(), v.getPermissionName());

            // 拼装父子权限映射
            if (Objects.isNull(v.getParentPermissionCode())) {
                // 顶级节点, 直接初始化父节点
                parent2SonPermissionCodeMap.put(v.getPermissionCode(), Lists.newArrayList());
                topPermissionCodes.add(v.getPermissionCode());
            } else {
                // 子节点, 则添加子集中
                List<String> sonPermissionCodes = parent2SonPermissionCodeMap.getOrDefault(v.getParentPermissionCode(), Lists.newArrayList());
                sonPermissionCodes.add(v.getPermissionCode());
                parent2SonPermissionCodeMap.put(v.getParentPermissionCode(), sonPermissionCodes);
            }
        }

        // 根据组装完成的集合构建权限树形结构返回对象
        return new SearchPermissionResp("root", "根节点",
                topPermissionCodes.stream().map(v -> buildPermissionTree(v, parent2SonPermissionCodeMap, permissionCode2NameMap))
                        .collect(Collectors.toList()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignRoles2User(AssignRoleToUserReq req) {
        // 校验用户是否存在
        if (Objects.isNull(sysUserFacade.searchSysUserById(Long.valueOf(req.getUserId())))) {
            throw BusinessException.get("当前用户不存在");
        }

        // 取出本次传入的所有用户id集合
        List<Long> assignRoleIds = req.getRoleIds().stream().filter(StringUtils::isNotBlank).map(Long::valueOf).distinct().toList();

        // 批量保存到数据库
        userRoleRelationMapper.batchInsertUserRoleRelation(assignRoleIds.stream().map(v -> {
            UserRoleRelation userRoleRelation = new UserRoleRelation();
            userRoleRelation.setUserId(Long.valueOf(req.getUserId()));
            userRoleRelation.setRoleId(v);
            return userRoleRelation;
        }).collect(Collectors.toList()));

        // 使用权限框架更新缓存中的用户角色
        PermissionUtils.assignCacheUserRoles(Long.valueOf(req.getUserId()), assignRoleIds, true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignPermissions2Role(AssignPermissionsToRoleReq req) {
        // 校验角色是否存在
        if (Objects.isNull(sysRoleFacade.searchSysRoleById(Long.valueOf(req.getRoleId())))) {
            throw BusinessException.get("当前角色不存在");
        }

        // 保存新的权限到数据库
        sysRoleFacade.editSysRolePermissions(Long.valueOf(req.getRoleId()), req.getPermissionCodes());
        // 使用权限框架保存权限
        PermissionUtils.assignCacheRolePermissions(Long.valueOf(req.getRoleId()), req.getPermissionCodes(), true);
    }

    @Override
    public SearchUserRoleRelationResp searchUserRoleRelation(Long userId) {
        boolean isSuperAdmin = PermissionUtils.verifyUserIsSuperAdmin(userId);
        if (!isSuperAdmin && Objects.isNull(sysUserFacade.searchSysUserById(userId))) {
            throw BusinessException.get("当前用户不存在");
        }

        SearchUserRoleRelationResp resp = new SearchUserRoleRelationResp();
        resp.setUserId(String.valueOf(userId));
        resp.setRelationRoles(Lists.newArrayList());

        // 拥有的角色集合
        List<SysRole> sysRoles = Lists.newArrayList();
        if (isSuperAdmin) {
            sysRoles = sysRoleFacade.searchAllSysRoles();
        } else {
            List<Long> roleIds = userRoleRelationMapper.searchRoleIdsByUserId(userId);
            if (CollectionUtils.isNotEmpty(roleIds)) {
                sysRoles = sysRoleFacade.searchSysRoleByIds(roleIds);
            }
        }
        if (CollectionUtils.isEmpty(sysRoles)) {
            return resp;
        }

        // 填充用户的角色信息
        resp.getRelationRoles().addAll(
                sysRoles.stream().map(v -> new RelationRoleInfoDto(String.valueOf(v.getId()), v.getRoleName())).toList());

        return resp;
    }

    @Override
    public SearchUserPermissionResp searchPermissionByUserId(Long userId) {
        boolean isSuperAdmin = PermissionUtils.verifyUserIsSuperAdmin(userId);
        if (!isSuperAdmin && Objects.isNull(sysUserFacade.searchSysUserById(userId))) {
            throw BusinessException.get("当前用户不存在");
        }

        SearchUserPermissionResp result = new SearchUserPermissionResp();
        result.setUserId(String.valueOf(userId));
        result.setPermissions(Lists.newArrayList());

        // 拥有的角色集合
        List<SysRole> sysRoles = Lists.newArrayList();
        if (isSuperAdmin) {
            sysRoles = sysRoleFacade.searchAllSysRoles();
        } else {
            List<Long> roleIds = userRoleRelationMapper.searchRoleIdsByUserId(userId);
            if (CollectionUtils.isNotEmpty(roleIds)) {
                sysRoles = sysRoleFacade.searchSysRoleByIds(roleIds);
            }
        }

        // 填充当前用户拥有的所有权限标识
        result.getPermissions().addAll(sysRoles.stream().map(SysRole::getPermissions).
                filter(StringUtils::isNotBlank).map(v -> v.split(",")).flatMap(Arrays::stream).distinct()
                .map(v -> new PermissionDto(v, PermissionEnum.getNameByCode(v))).toList());

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unbindUserRoleRelation(Long userId, Long roleId) {
        if (Objects.isNull(sysUserFacade.searchSysUserById(userId))) {
            throw BusinessException.get("当前用户不存在");
        }

        // 无论角色是否存在,直接删除关联即可
        userRoleRelationMapper.deleteUserRoleRelationByUserIdAndRoleId(userId, roleId);
    }

    @Override
    public void refreshCachePermissions() {
        // 查询系统所有的角色
        List<SysRole> sysRoles = sysRoleFacade.searchAllSysRoles();
        if (CollectionUtils.isEmpty(sysRoles)) {
            return;
        }

        // 循环此次处理每个角色
        for (SysRole sysRole : sysRoles) {
            Set<String> permissions = Sets.newHashSet();
            if (StringUtils.isNotBlank(sysRole.getPermissions())) {
                permissions = Sets.newHashSet(sysRole.getPermissions().split(","));
            }

            // 使用权限框架进行同步
            PermissionUtils.assignCacheRolePermissions(sysRole.getId(), permissions, true);
        }
    }

    /**
     * 构建权限树返回对象
     *
     * @param permissionCode              权限编码
     * @param parent2SonPermissionCodeMap 父子权限映射
     * @param permissionCode2NameMap      权限编码名称映射
     */
    private SearchPermissionResp buildPermissionTree(String permissionCode,
                                                     Map<String, List<String>> parent2SonPermissionCodeMap,
                                                     Map<String, String> permissionCode2NameMap) {
        SearchPermissionResp resp = new SearchPermissionResp();
        resp.setPermissionCode(permissionCode);
        resp.setPermissionName(permissionCode2NameMap.get(permissionCode));
        resp.setSonPermissions(Lists.newArrayList());

        // 取出当前节点的子节点集合
        List<String> sonPermissionCodes = parent2SonPermissionCodeMap.getOrDefault(permissionCode, Collections.emptyList());
        if (CollectionUtils.isEmpty(sonPermissionCodes)) {
            return resp;
        }

        // 循环递归构建子节点
        for (String sonPermissionCode : sonPermissionCodes) {
            SearchPermissionResp sonSearchPermissionResp = buildPermissionTree(sonPermissionCode, parent2SonPermissionCodeMap, permissionCode2NameMap);
            resp.getSonPermissions().add(sonSearchPermissionResp);
        }

        return resp;
    }

}
